package top.tresman.cxxcommon.interceptor;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import top.tresman.cxxcommon.config.AuthConfig;
import top.tresman.cxxcommon.entity.LoginUserDTO;
import top.tresman.cxxcommon.entity.constants.BaseRedisConstant;
import top.tresman.cxxcommon.entity.constants.ErrorCodeEnum;
import top.tresman.cxxcommon.exception.ApiException;
import top.tresman.cxxcommon.utils.AuthUtils;
import top.tresman.cxxcommon.utils.RedisUtils;

import java.util.Arrays;
import java.util.stream.Collectors;


/**
 * @author hexiang
 * @desc
 */
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private AuthConfig authConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod handlerMethod)) {
            return true;
        }
        RequestMapping requestMappingAnno = handlerMethod.getMethodAnnotation(RequestMapping.class);
        if (requestMappingAnno == null) {
            return true;
        }

        String routeName = requestMappingAnno.name();

        log.info("请求路由名为:{}，请求路径为：{} {}", routeName, request.getMethod(), request.getRequestURI());

        if (authConfig.getNoLoginRoutes().contains(routeName)) {
            return true;
        }

        //验证token信息是否存在
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("token");
            if (StringUtils.isEmpty(token)) {
                throw new ApiException(ErrorCodeEnum.INVALID_TOKEN, "token不能为空");
            }
        }

        String[] split = token.split(":");
        if (split.length < 2) {
            throw new ApiException(ErrorCodeEnum.INVALID_TOKEN, "token格式错误");
        }

        String prefix = split[0];

        token = Arrays.stream(split).skip(1).collect(Collectors.joining(":"));

        String loginKey = BaseRedisConstant.getLoginKey(prefix, token);
        LoginUserDTO.UserInfo userInfo = redisUtils.get(loginKey, LoginUserDTO.UserInfo.class);
        if (userInfo == null) {
            response.setStatus(401);
            throw new ApiException(ErrorCodeEnum.INVALID_TOKEN, "用户信息登陆信息失效，请重新登陆");
        }

        LoginUserDTO loginUser = new LoginUserDTO();
        loginUser.setToken(token);
        loginUser.setTokenPrefix(prefix);
        loginUser.setUser(userInfo);
        AuthUtils.setLoginUser(loginUser);

        long ttl = redisUtils.ttl(loginKey);
        if (ttl <= 600) {
            redisUtils.expire(loginKey, authConfig.getLoginExpireSec());
        }

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3)
            throws Exception {

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3) throws Exception {

    }
}
